package com.eight.cloud.client.util;


import cn.hutool.core.util.StrUtil;
import com.eight.cloud.client.common.Constant;
import org.springframework.util.StreamUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * @ClassName: SignatureUtil
 * @Description: 数据签名工具类
 * @Author: TXC
 * @Date: 2024-10-18 10:48
 **/
public class SignatureUtil {
	/**
	 * 生成签名
	 *
	 * @param secretKey 密钥
	 * @param data 数据
	 * @return java.lang.String
	 * @Author: TXC
	 * @Date: 2024/12/18 10:53
	 */
	public static String generateSignature(String secretKey, String data) {
		try {
			String message = secretKey + data;
			byte[] rawHmac = generateHmac(message, secretKey);
			return bytesToHex(rawHmac);
		} catch (InvalidKeyException | NoSuchAlgorithmException e) {
			throw new RuntimeException("签名算法异常", e);
		}
	}
	/**
	 * @Description: HmacSHA256算法加密
	 *
	 * @param message 需要加密的数据
	 * @param secretKey 密钥
	 * @return java.lang.String
	 * @Author: TXC
	 * @Date: 2024/12/18 10:50
	 */
	private static byte[] generateHmac(String message, String secretKey) throws NoSuchAlgorithmException, InvalidKeyException {
		Mac mac = Mac.getInstance("HmacSHA256");
		SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
		mac.init(secretKeySpec);
		return mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * 字节数组转16进制字符串
	 * @param bytes 字节数组
	 * @return
	 */
	private static String bytesToHex(byte[] bytes) {
		StringBuilder result = new StringBuilder();
		for (byte b : bytes) {
			result.append(String.format("%02x", b));
		}
		return result.toString();
	}

	/**
	 * 校验签名
	 * @param secretKey 密钥
	 * @param data 数据
	 * @param signature 签名
	 * @return 校验结果
	 */
	public static boolean verifySignature(String secretKey, String data, String signature) {
		return generateSignature(secretKey, data).equals(signature);
	}

	/**
     * post请求处理：获取 Body 参数，转换为SortedMap
     *
     * @param request
     */
    public static SortedMap<String, Object> getBodyParams(final HttpServletRequest request) throws IOException {
        byte[] requestBody = StreamUtils.copyToByteArray(request.getInputStream());
        return ObjectFormat.byteToObj(SortedMap.class, requestBody);
    }


    /**
     * get请求处理：将URL请求参数转换成SortedMap
     */
    public static SortedMap<String, Object> getUrlParams(final HttpServletRequest request) {
        String param = "";
        SortedMap<String, Object> result = new TreeMap<>();

        if (StrUtil.isEmpty(request.getQueryString())) {
            return result;
        }
        param = URLDecoder.decode(request.getQueryString(), StandardCharsets.UTF_8);
		return getUrlParams(param);
    }

	public static SortedMap<String, Object> getUrlParams(final String queryString) {
		String param = "";
		SortedMap<String, Object> result = new TreeMap<>();
		if (StrUtil.isEmpty(queryString)) {
			return result;
		}
		param = URLDecoder.decode(queryString, StandardCharsets.UTF_8);
		String[] params = param.split("&");
		for (String s : params) {
			String[] array=s.split(Constant.EQUAL);
			result.put(array[Constant.ZERO], array[Constant.ONE]);
		}
		return result;
	}

    public static String getRequestParams(final HttpServletRequest request) throws IOException {
        String method = request.getMethod();
        if (StrUtil.equalsIgnoreCase(method, Constant.POST)) {
            return ObjectFormat.objectToStr(getBodyParams(request));
        } else if (StrUtil.equalsIgnoreCase(method, Constant.GET)) {
            return ObjectFormat.objectToStr(getUrlParams(request));
        } else {
            return null;
        }
    }

	/**
	 * 获取指定长度的随机字符串
	 * @param length 长度
	 * @return 随机字符串
	 */
	public static String getRandomStr(int length) {
		SecureRandom random = new SecureRandom();
		byte[] bytes = new byte[length];
		random.nextBytes(bytes);
		return Base64.getEncoder().encodeToString(bytes);
	}
}
